<template>
  <j-modal
    title="选择部门"
    :width="modalWidth"
    :visible="visible"
    :confirmLoading="confirmLoading"
    @cancel="handleCancel"
    wrapClassName="j-depart-select-modal"
    switchFullscreen
    cancelText="关闭"
  >
    <a-spin tip="Loading..." :spinning="false">
      <a-input-search style="margin-bottom: 1px" placeholder="请输入部门名称按回车进行搜索" @search="onSearch" />
      <a-tree
        checkable
        class="my-dept-select-tree"
        :treeData="treeData"
        @check="onCheck"
        @select="onSelect"
        @expand="onExpand"
        :autoExpandParent="autoExpandParent"
        :checkStrictly="checkStrictly"
        :selectedKeys="[]"
        :expandedKeys="expandedKeys"
        :checkedKeys="checkedKeys"
      >
        <template slot="title" slot-scope="{ title }">
          <span v-if="title.indexOf(searchValue) > -1">
            {{ title.substr(0, title.indexOf(searchValue)) }}
            <span style="color: #f50">{{ searchValue }}</span>
            {{ title.substr(title.indexOf(searchValue) + searchValue.length) }}
          </span>
          <span v-else>{{ title }}</span>
        </template>
      </a-tree>
    </a-spin>

    <div class="drawer-bootom-button" slot="footer">
      <a-dropdown v-if="operationList.length !== 0" style="float: left" :trigger="['click']" placement="topCenter">
        <a-menu slot="overlay">
          <a-menu-item v-if="operationList.includes('CHECK_ALL')" key="CHECK_ALL" @click="checkALL">全部勾选</a-menu-item>
          <a-menu-item v-if="operationList.includes('CANCEL_CHECK_ALL')" key="CANCEL_CHECK_ALL" @click="cancelCheckALL">
            取消全选
          </a-menu-item>
          <a-menu-item v-if="operationList.includes('EXPAND_ALL')" key="EXPAND_ALL" @click="expandAll">展开所有
          </a-menu-item>
          <a-menu-item v-if="operationList.includes('CLOSE_ALL')" key="CLOSE_ALL" @click="closeAll">合并所有</a-menu-item>
        </a-menu>
        <a-button>
          树操作
          <a-icon type="up" />
        </a-button>
      </a-dropdown>

      <a-button @click="handleCancel" style="margin-right: .8rem">取消</a-button>
      <a-button @click="handleSubmit" type="primary" :loading="confirmLoading">确定</a-button>
    </div>

  </j-modal>
</template>

<script>
  import { getChildrenKeyList, getTreeNodeByKey, mapTree } from '@/utils/tree'
  import { queryDepartTreeList } from '@/api/api'

  export default {
    name: 'PDepartSelectModal',
    props: ['modalWidth', 'multi', 'isOnlySelectLeaf', 'checkStrictly', 'rootId', 'operationList', 'rootOpened', 'disabledDepartNameList', 'departId'],
    data() {
      return {
        visible: false,
        confirmLoading: false,
        treeData: [],
        autoExpandParent: true,
        expandedKeys: [],
        dataList: [],
        checkedKeys: [],
        checkedRows: [],
        allTreeKeys: [],
        searchValue: ''
      }
    },
    created() {
      this.loadDepart()
    },
    computed: {},
    watch: {
      departId() {
        this.initDepartComponent()
      },
      visible: {
        handler() {
          if (this.departId) {
            this.checkedKeys = this.departId.split(',')
          // console.log('this.departId', this.departId)
          } else {
            this.checkedKeys = []
          }
        }
      }
    },
    methods: {
      show() {
        this.visible = true
        this.checkedRows = []
        this.checkedKeys = []
      },
      filterTreeData(arr) {
        this.disabledDepartNameList.forEach(name => {
          let node = getTreeNodeByKey(arr, name, 'departName')
          if (node) {
            // 这里node改了以后会直接改变treeData，因为node是内存地址
            node.disabled = true
          }
        })
        return arr
      },
      filterRootIdTreeData(arr) {
        let node = getTreeNodeByKey(arr, this.rootId, 'id')
        if (node) {
          return [node]
        }
        return arr
      },
      setOnlySelectLeafTreeData(arr) {
        return mapTree(arr, (item) => {
          item.disableCheckbox = !item.isLeaf
          item.selectable = item.isLeaf
          return item
        })
      },
      loadDepart() {
        // 这个方法是找到所有的部门信息
        queryDepartTreeList().then((res) => {
          if (res.success) {
            let arr = res.result ? [...res.result] : []
            // 过滤和rootId无关的内容
            if (this.rootId) {
              arr = this.filterRootIdTreeData(arr)
            }
            if (this.isOnlySelectLeaf) {
              arr = this.setOnlySelectLeafTreeData(arr)
            }
            this.reWriterWithSlot(arr)
            this.treeData = this.filterTreeData(arr)
            this.initDepartComponent()
            if (this.rootOpened) {
              this.initExpandedKeys(res.result)
              this.allTreeKeys = this.lookForAllId(res.result, [])
            }
          }
        })
      },
      checkALL() {
        this.checkedKeys = JSON.parse(JSON.stringify(this.allTreeKeys))
        this.checkedRows = this.getCheckedRows(this.checkedKeys)
      },
      cancelCheckALL() {
        this.checkedKeys = []
        this.checkedRows = []
      },
      expandAll() {
        this.expandedKeys = JSON.parse(JSON.stringify(this.allTreeKeys))
      },
      closeAll() {
        this.expandedKeys = []
      },
      initDepartComponent() {
        let names = ''
        if (this.departId) {
          let currDepartId = this.departId
          for (let item of this.dataList) {
            if (currDepartId.indexOf(item.key) >= 0) {
              names += ',' + item.title
            }
          }
          if (names) {
            names = names.substring(1)
          }
        }
        this.$emit('initComp', names)
      },
      reWriterWithSlot(arr) {
        for (let item of arr) {
          if (item.children && item.children.length > 0) {
            this.reWriterWithSlot(item.children)
            let temp = Object.assign({}, item)
            temp.children = {}
            this.dataList.push(temp)
          } else {
            this.dataList.push(item)
            item.scopedSlots = { title: 'title' }
          }
        }
      },
      initExpandedKeys(arr) {
        if (arr && arr.length > 0) {
          let keys = []
          for (let item of arr) {
            if (item.children && item.children.length > 0) {
              keys.push(item.id)
            }
          }
          this.expandedKeys = [...keys]
        } else {
          this.expandedKeys = []
        }
      },
      lookForAllId(data = [], arr = []) {
        for (let item of data) {
          arr.push(item.id)
          if (item.children && item.children.length) {
            this.lookForAllId(item.children, arr)
          }
        }
        return arr
      },
      onCheck(checkedKeys, info) {
        // 父子关联时
        if (this.checkStrictly) {
          if (this.multi) {
            this.checkedKeys = checkedKeys
            this.checkedRows = this.getCheckedRows(this.checkedKeys)
          } else {
            let arr = checkedKeys.checked.filter(item => this.checkedKeys.indexOf(item) < 0)
            this.checkedKeys = [...arr]
            this.checkedRows = (this.checkedKeys.length === 0) ? [] : [info.node.dataRef]
          }
          return
        }

        // 父子不关联时
        if (this.multi) {
          this.checkedKeys = checkedKeys
          this.checkedRows = this.getCheckedRows(this.checkedKeys)
        } else {
          let arr = checkedKeys.filter(item => this.checkedKeys.indexOf(item) < 0)
          this.checkedKeys = [...arr]
          this.checkedRows = (this.checkedKeys.length === 0) ? [] : [info.node.dataRef]
        }
      },
      onSelect(selectedKeys, info) {
        let currKey = info.node.dataRef.key
        if (!this.multi) {
          this.checkedKeys = [currKey]
          this.checkedRows = [info.node.dataRef]
          return
        }

        let parentKey = this.getParentKey(currKey, this.treeData)
        let currentNode = getTreeNodeByKey(this.treeData, currKey, 'id')
        let childIds = getChildrenKeyList(currentNode.children)
        if (this.checkedKeys.indexOf(currKey) >= 0) {
          // 取消选中后，自己、父节点、子节点也要全部取消勾选
          this.checkedKeys = this.checkedKeys.filter((item) => ![currKey, parentKey, ...childIds].includes(item))
        } else {
          // 选中后，自己、子节点也要全部勾选
          this.checkedKeys.push(currKey, ...childIds)
        }
        this.$set(this, 'checkedKeys', this.checkedKeys)
        this.$set(this, 'checkedRows', this.getCheckedRows(this.checkedKeys))
      },
      onExpand(expandedKeys) {
        this.expandedKeys = expandedKeys
        this.autoExpandParent = false
      },
      handleSubmit() {
        if (!this.checkedKeys || this.checkedKeys.length === 0) {
          this.$emit('ok', '')
        } else {
          let checkRow = this.getCheckedRows(this.checkedKeys)
          let keyStr = this.checkedKeys.join(',')
          this.$emit('ok', checkRow, keyStr)
        }
        this.handleClear()
      },
      handleCancel() {
        this.handleClear()
      },
      handleClear() {
        this.visible = false
        this.checkedKeys = []
      },
      getParentKey(currKey, treeData) {
        let parentKey
        for (let i = 0; i < treeData.length; i++) {
          const node = treeData[i]
          if (node.children) {
            if (node.children.some((item) => item.key === currKey)) {
              parentKey = node.key
            } else if (this.getParentKey(currKey, node.children)) {
              parentKey = this.getParentKey(currKey, node.children)
            }
          }
        }
        return parentKey
      },
      onSearch(value) {
        const expandedKeys = this.dataList
          .map((item) => {
            if (item.title.indexOf(value) > -1) {
              return this.getParentKey(item.key, this.treeData)
            }
            return null
          })
          .filter((item, i, self) => item && self.indexOf(item) === i)

        Object.assign(this, {
          expandedKeys,
          searchValue: value,
          autoExpandParent: true
        })
      },
      // 根据 checkedKeys 获取 rows
      getCheckedRows(checkedKeys) {
        const forChildren = (list, key) => {
          for (let item of list) {
            if (item.id === key) {
              return item
            }
            if (item.children instanceof Array) {
              let value = forChildren(item.children, key)
              if (value != null) {
                return value
              }
            }
          }
          return null
        }

        let rows = []
        for (let key of checkedKeys) {
          let row = forChildren(this.treeData, key)
          if (row != null) {
            rows.push(row)
          }
        }
        return rows
      }
    }
  }
</script>

<style lang='less' scoped>
// 限制部门选择树高度，避免部门太多时点击确定不便
.my-dept-select-tree {
  height: 350px;
  overflow-y: scroll;
}
</style>
